﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework;

namespace Tomahawk.Runtime.Player
{
    /// <summary>
    /// This class help managing the logged in players, and their rich presence.
    /// </summary>
    public class PlayerManager
    {
        /// <summary>
        /// This class stores the information of a player
        /// </summary>
        public class Player
        {
            /// <summary>
            /// Logic index of the player in the logged player array
            /// </summary>
            public PlayerIndex LogicIndex;

            /// <summary>
            /// Gamepad used bt this player
            /// </summary>
            public PlayerIndex GamepadIndex;

            /// <summary>
            /// Gamer profile associated to the player
            /// (it'd be null for guest players)
            /// </summary>
            public SignedInGamer Gamer;

            /// <summary>
            /// Name of the player
            /// </summary>
            public String Name;

            /// <summary>
            /// Indicates if the players is a guest of another player
            /// (who can participate in network games)
            /// </summary>
            public bool IsGuest { get; internal set; }

            /// <summary>
            /// For Guest players, this property point to the host player
            /// </summary>
            public Player HostPlayer { get; internal set; }

            /// <summary>
            /// Gets if the player can participate in network games
            /// </summary>
            public bool IsNetworkGameCapable { get; internal set; }

        }

        /// <summary>
        /// Default player
        /// </summary>
        private Player defaultPlayer = null;

        /// <summary>
        /// Players logged in the game
        /// </summary>
        private Dictionary<PlayerIndex, Player> logedPlayers;

        /// <summary>
        /// Players logged into the game
        /// </summary>
        public Dictionary<PlayerIndex, Player> LogedPlayers
        {
            get { return this.logedPlayers; }
        }

        /// <summary>
        /// This is the default player, or "Master" player
        /// </summary>
        public Player DefaultPlayer
        {
            get { return defaultPlayer; }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public PlayerManager()
        {
            logedPlayers = new Dictionary<PlayerIndex, Player>();
        }

        #region "Simple player sign-in for 1player-only games"

        /// <summary>
        /// Sign in the first player that has a Live profile associated
        /// </summary>
        public void SimpleSignInSinglePlayerWithProfile()
        {
            this.logPlayerIn(Gamer.SignedInGamers[0], PlayerIndex.One);
        }

        /// <summary>
        /// 
        /// </summary>
        public void SimpleSingInSinglePlayerWithNoProfile()
        {
            //sign the null player as the logic player
            this.logPlayerIn(null, PlayerIndex.One);
        }

        #endregion

        #region "Player Sign-In"

        /// <summary>
        /// Sign in a guest player
        /// </summary>
        public void SignInGuestPlayer(PlayerIndex gamePadIndex)
        {
            this.logPlayerIn(null, gamePadIndex);
        }

        /// <summary>
        /// Try to sign in a player that has a valid Live profile signed in.
        /// If the gameped specified is not currently associated to an Live profile
        /// the method will return false, and no player will be logged
        /// </summary>
        public bool TrySignInProfilePlayer(PlayerIndex gamePadIndex)
        {
            bool retVal = false;
            foreach (SignedInGamer gamer in Gamer.SignedInGamers)
            {
                if (gamer.PlayerIndex == gamePadIndex)
                {
                    this.logPlayerIn(gamer, gamePadIndex);
                    retVal = true;
                }
            }
            return retVal;
        }

        #endregion

        /*
        /// <summary>
        /// Sign in the players that's using the indicated gamepad, using a valid live profile
        /// </summary>
        public bool SignInPlayer(PlayerIndex padIndex)
        {
            return this.SignInPlayer(padIndex, true);
        }

        /// <summary>
        /// Sign in the player that's using the indicated gamepad
        /// </summary>
        public bool SignInPlayer(PlayerIndex padIndex, bool forceProfile)
        {
            bool retVal = false;

            if (forceProfile)
            {
                foreach (SignedInGamer gamer in Gamer.SignedInGamers)
                {
                    if (gamer.PlayerIndex == padIndex)
                    {
                        this.logPlayerIn(gamer, padIndex);
                        retVal = true;
                    }
                }
            }
            else
            {
                this.logPlayerIn(null, padIndex);
                retVal = true;
            }
            return retVal;
        }
        */

        /// <summary>
        /// Add a player to the logged players dictionary
        /// </summary>
        private void logPlayerIn(SignedInGamer gamer, PlayerIndex padIndex)
        {
            //create the player logic wrapper
            Player player = new Player();

            //if there's no default player assigned yer, assign it
            PlayerIndex currIndex = PlayerIndex.One;
            if (this.defaultPlayer == null)
            {
                this.defaultPlayer = player;
            }
            else
            {
                //if the default player has no profile, and the new player has
                //exchange them
                if ((gamer != null) && (this.defaultPlayer.Gamer == null))
                {
                    this.defaultPlayer = player;
                }

                //get highest logic index
                PlayerIndex highIndex = PlayerIndex.One;
                foreach (Player p in this.logedPlayers.Values)
                {
                    if ((int)p.LogicIndex > (int)highIndex) highIndex = p.LogicIndex;
                }
                currIndex = (PlayerIndex)((int)highIndex + 1);
            }

            //assign player properties
            player.Gamer = gamer;
            player.LogicIndex = currIndex;

            //asign name
            if (gamer != null)
            {
                player.Name = gamer.Gamertag;
            }
            else
            {
                player.Name = "Unnamed_" + player.LogicIndex.ToString();
            }

            //assign game pad
            if (gamer != null)
            {
                player.GamepadIndex = gamer.PlayerIndex;
            }
            else
            {
                player.GamepadIndex = padIndex;
            }

            //set the guest/network flags and properties
            if (player.Gamer != null)
            {
                player.IsGuest = false;
                player.HostPlayer = null;
                player.IsNetworkGameCapable = player.Gamer.IsSignedInToLive && player.Gamer.Privileges.AllowOnlineSessions;
            }
            else
            {
                player.IsGuest = true;
                player.HostPlayer = this.defaultPlayer;
                player.IsNetworkGameCapable = false;
            }

            //activate input processing on its gamepad
            Engine.Instance.InputManager.ActivateKeypadProcessing(player.GamepadIndex, true);

            //add to logged players dictionary
            this.logedPlayers.Add(player.LogicIndex, player);
        }



    }

}
